home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / explode.c < prev    next >
C/C++ Source or Header  |  1992-11-16  |  7KB  |  239 lines

  1. /*    SCCS Id: @(#)explode.c 3.1    90/11/06
  2. /*    Copyright (C) 1990 by Ken Arromdee */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. /* Note: Arrays are column first, while the screen is row first */
  8. static int expl[3][3] = 
  9. { S_explode1, S_explode4, S_explode7,
  10.   S_explode2, S_explode5, S_explode8,
  11.   S_explode3, S_explode6, S_explode9 };
  12.  
  13. /* Note: I had to choose one of three possible kinds of "type" when writing
  14.  * this function: a wand type (like in zap.c), an adtyp, or an object type.
  15.  * Wand types get complex because they must be converted to adtyps for
  16.  * determining such things as fire resistance.  Adtyps get complex in that
  17.  * they don't supply enough information--was it a player or a monster that
  18.  * did it, and with a wand, spell, or breath weapon?  Object types share both
  19.  * these disadvantages....
  20.  */
  21. void
  22. explode(x, y, type, dam, olet)
  23. int x, y;
  24. int type; /* the same as in zap.c */
  25. int dam;
  26. char olet;
  27. {
  28.     int i, j, k;
  29.     boolean starting = 1;
  30.     boolean visible, any_shield;
  31.     int uhurt = 0; /* 0=unhurt, 1=items damaged, 2=you and items damaged */
  32.     const char *str;
  33.     int idamres, idamnonres;
  34.     struct monst *mtmp;
  35.     uchar adtyp;
  36.     int explmask[3][3];
  37.         /* 0=normal explosion, 1=do shieldeff, 2=do nothing */
  38.     boolean shopdamage = FALSE;
  39.  
  40.     switch(abs(type) % 10) {
  41.         default: impossible("explosion base type %d?", type); return;
  42.  
  43.         case 1: str = (olet == SCROLL_CLASS ? "tower of flame" : "fireball"); adtyp = AD_FIRE; break;
  44.         /* case 3: str = "ball of cold"; adtyp = AD_COLD; break; */
  45.         /* case 5: str = "ball lightning"; adtyp = AD_ELEC; break; */
  46.         /* case 7: str = "acid ball"; adtyp = AD_ACID; break; */
  47.     }
  48.  
  49.     any_shield = visible = FALSE;
  50.     for(i=0; i<3; i++) for(j=0; j<3; j++) {
  51.         if (!isok(i+x-1, j+y-1)) {
  52.             explmask[i][j] = 2;
  53.             continue;
  54.         }
  55.         if (i+x-1 == u.ux && j+y-1 == u.uy) {
  56.             switch(adtyp) {
  57.             case AD_FIRE:
  58.                 explmask[i][j] = Fire_resistance ? 1 : 0;
  59.                 break;
  60.             /* case AD_COLD: */
  61.             /* case AD_ELEC: */
  62.             /* case AD_DISN: */
  63.             /* case AD_ACID: */
  64.             default:
  65.                 impossible("explosion type %d?", adtyp);
  66.                 explmask[i][j] = 0;
  67.                 break;
  68.             }
  69.         }
  70.         /* can be both you and mtmp if you're swallowed */
  71.         if (mtmp = m_at(i+x-1, j+y-1)) {
  72.             switch(adtyp) {
  73.             case AD_FIRE:
  74.                 explmask[i][j] = resists_fire(mtmp->data)
  75.                     ? 1 : 0;
  76.                 break;
  77.             /* case AD_COLD: */
  78.             /* case AD_ELEC: */
  79.             /* case AD_DISN: */
  80.             /* case AD_ACID: */
  81.             default:
  82.                 impossible("explosion type %d?", adtyp);
  83.                 explmask[i][j] = 0;
  84.                 break;
  85.             }
  86.         } else if (i+x-1 != u.ux || j+j-1 != u.uy)
  87.             explmask[i][j] = 0;
  88.  
  89.         if (cansee(i+x-1, j+y-1)) visible = TRUE;
  90.         if (explmask[i][j] == 1) any_shield = TRUE;
  91.     }
  92.  
  93.     if (visible) {
  94.         /* Start the explosion */
  95.         for(i=0; i<3; i++) for(j=0; j<3; j++) {
  96.             if (explmask[i][j] == 2) continue;
  97.             tmp_at(starting ? DISP_BEAM : DISP_CHANGE,
  98.                         cmap_to_glyph(expl[i][j]));
  99.             tmp_at(i+x-1, j+y-1);
  100.             starting = 0;
  101.         }
  102.         curs_on_u();    /* will flush screen and output */
  103.  
  104.         if (any_shield) {    /* simulate a shield effect */
  105.             for (k = 0; k < SHIELD_COUNT; k++) {
  106.             for(i=0; i<3; i++) for(j=0; j<3; j++) {
  107.                 if (explmask[i][j] == 1)
  108.                 /*
  109.                  * Bypass tmp_at() and send the shield glyphs
  110.                  * directly to the buffered screen.  tmp_at()
  111.                  * will clean up the location for us later.
  112.                  */
  113.                 show_glyph(i+x-1, j+y-1,
  114.                     cmap_to_glyph(shield_static[k]));
  115.             }
  116.             curs_on_u();    /* will flush screen and output */
  117.             delay_output();
  118.             }
  119.  
  120.             /* Cover last shield glyph with blast symbol. */
  121.             for(i=0; i<3; i++) for(j=0; j<3; j++) {
  122.             if (explmask[i][j] == 1)
  123.                 show_glyph(i+x-1,j+y-1,cmap_to_glyph(expl[i][j]));
  124.             }
  125.  
  126.         } else {        /* delay a little bit. */
  127.             delay_output();
  128.             delay_output();
  129.         }
  130.  
  131.     } else You("hear a blast.");
  132.  
  133.  
  134.     for(i=0; i<3; i++) for(j=0; j<3; j++) {
  135.         if (explmask[i][j] == 2) continue;
  136.         if (i+x-1 == u.ux && j+y-1 == u.uy)
  137.             uhurt = (explmask[i][j] == 1) ? 1 : 2;
  138.         idamres = idamnonres = 0;
  139.         (void)zap_over_floor((xchar)(i+x-1), (xchar)(j+y-1),
  140.                      type, &shopdamage);
  141.  
  142.         mtmp = m_at(i+x-1, j+y-1);
  143.         if (!mtmp) continue;
  144.         if (u.uswallow && mtmp == u.ustuck) {
  145.             if (is_animal(u.ustuck->data))
  146.                 pline("%s gets heartburn!",
  147.                       Monnam(u.ustuck));
  148.             else
  149.                 pline("%s gets toasted slightly!",
  150.                       Monnam(u.ustuck));
  151.         } else
  152.         pline("%s is caught in the %s!",
  153.             cansee(i+x-1, j+y-1) ? Monnam(mtmp) : "It", str);
  154.  
  155.         idamres += destroy_mitem(mtmp, SCROLL_CLASS, (int) adtyp);
  156.         idamres += destroy_mitem(mtmp, SPBOOK_CLASS, (int) adtyp);
  157.         /* Fire resistance protects monsters from burning scrolls, */
  158.         /* but not from exploding potions. */
  159.         idamnonres += destroy_mitem(mtmp, POTION_CLASS, (int) adtyp);
  160. /*
  161.         idamnonres += destroy_mitem(mtmp, WAND_CLASS, (int) adtyp);
  162.         idamnonres += destroy_mitem(mtmp, RING_CLASS, (int) adtyp);
  163. */
  164.         if (explmask[i][j] == 1) {
  165.             golemeffects(mtmp, (int) adtyp, dam + idamres);
  166.             mtmp->mhp -= idamnonres;
  167.         } else {
  168.         /* call resist with 0 and do damage manually so 1) we can
  169.          * get out the message before doing the damage, and 2) we can
  170.          * call mondied, not killed, if it's not your blast
  171.          */
  172.             int mdam = dam;
  173.  
  174.             if (resist(mtmp, olet, 0, FALSE)) {
  175.                 pline("%s resists the magical blast!",
  176.                     cansee(i+x-1,j+y-1) ? Monnam(mtmp)
  177.                     : "It");
  178.                 mdam = dam/2;
  179.             }
  180.             if (mtmp == u.ustuck)
  181.                 mdam *= 2;
  182.             if (resists_cold(mtmp->data) /* && adtyp == AD_FIRE */)
  183.                 mdam *= 2;
  184.             mtmp->mhp -= mdam;
  185.             mtmp->mhp -= (idamres + idamnonres);
  186.         }
  187.         if (mtmp->mhp <= 0) {
  188.             if (type >= 0) killed(mtmp);
  189.             else mondied(mtmp);
  190.         }
  191.     }
  192.  
  193.     if (visible) tmp_at(DISP_END, 0); /* clear the explosion */
  194.  
  195.     /* Do your injury last */
  196.     if (uhurt) {
  197.             if (type >= 0 && flags.verbose && olet != SCROLL_CLASS)
  198.             You("are caught in the %s!", str);
  199.         if (uhurt == 2) u.uhp -= dam;
  200.         if (u.uhp <= 0) {
  201.             char buf[BUFSZ];
  202.  
  203.             if (type >= 0 && olet != SCROLL_CLASS) {
  204.                 killer_format = NO_KILLER_PREFIX;
  205.                 Sprintf(buf, "caught %sself in %s own %s.",
  206.                 flags.female ? "her" : "him",
  207.                 flags.female ? "her" : "his", str);
  208.             } else {
  209.                 killer_format = KILLED_BY;
  210.                 Strcpy(buf, str);
  211.             }
  212.             killer = buf;
  213.             /* done(adtyp == AD_FIRE ? BURNING : DIED); */
  214.             done(BURNING);
  215.         }
  216.         exercise(A_STR, FALSE);
  217. #if defined(POLYSELF)
  218.         ugolemeffects((int) adtyp, dam);
  219. #endif
  220.         destroy_item(SCROLL_CLASS, (int) adtyp);
  221.         destroy_item(SPBOOK_CLASS, (int) adtyp);
  222.         destroy_item(POTION_CLASS, (int) adtyp);
  223. /*
  224.         destroy_item(RING_CLASS, (int) adtyp);
  225.         destroy_item(WAND_CLASS, (int) adtyp);
  226. */
  227.     }
  228.     if (shopdamage) {
  229.         pay_for_damage("burn away");
  230. /* (only if we ever add non-fire balls)
  231.         pay_for_damage(adtyp == AD_FIRE ? "burn away" :
  232.                    adtyp == AD_COLD ? "shatter" :
  233.                    adtyp == AD_DISN ? "disintegrate" : "destroy");
  234. */
  235.     }
  236. }
  237.  
  238. /*explode.c*/
  239.